﻿/*-------------------------------------------------------------------------
* 命名空间: XrayDirection.Common/PlcCommunication
* 类       名: PlcCommunication
* 功      能:  TD
* 时      间:  2024/1/25 14:03:13
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using HslCommunication;
using HslCommunication.Profinet.Siemens;
using System;
using System.Collections.Generic;
using System.Linq;
using XrayDirection.Extensions;
using XrayDirection.Models;

namespace XrayDirection.Common
{
    public class PlcCommunication
    {
        private static PlcCommunication? _instance;
        private static readonly object _lock = new object();
        public DeviceState PlcState { get; private set; }
        public SiemensS7Net NetClient;

        private PlcCommunication()
        {
            PlcState = new DeviceState();
            PlcState.DeviceIp = "192.168.0.10";
            PlcState.DevicePort = 0;
            PlcState.IsOnline = false;
            NetClient = new SiemensS7Net(SiemensPLCS.S1200, PlcState.DeviceIp);
            NetClient.ConnectTimeOut = 100;
        }

        public static PlcCommunication Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new PlcCommunication();
                        }
                    }
                }
                return _instance;
            }
        }

        public DataResult ConnectPlc()
        {
            DataResult result = new DataResult();
            try
            {
                OperateResult connect = NetClient.ConnectServer();
                if (!connect.IsSuccess)
                {
                    result.Message = connect.Message;
                    PlcState.IsOnline = false;
                }
                else
                {
                    result.State = true;
                    PlcState.IsOnline = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 找板边拍照信号
        /// DB100.DBDO 
        /// PLC=1 表示已触发拍照
        ///上位机=2 表示数据接收采集完成
        /// PLC = 0 表示动作完毕初始化
        /// </summary>
        /// <returns></returns>
        public DataResult<int> GetAllowFindBoardEdgePic()
        {
            DataResult<int> result = new DataResult<int>();
            string readPos = "DB100.DBD100";
            try
            {
                OperateResult<int> readVal = NetClient.ReadInt32(readPos);
                if (readVal.IsSuccess)
                {
                    result.Data = readVal.Content;
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 获取报警信息,获取bool值为true的索引.然后根据这个索引,去显示报警信息.
        /// 报警信息从DB100.292.0 开始,然后后面一共100个报警信息
        /// </summary>
        /// <returns></returns>
        public DataResult<List<int>> GetAlarmInfo()
        {
            DataResult<List<int>> result = new DataResult<List<int>>();
            try
            {
                string readPos = "DB100.292.0";
                OperateResult<bool[]> readResult = NetClient.ReadBool(readPos, 100);
                if (readResult.IsSuccess)
                {
                    bool[] vals = readResult.Content;
                    var trueIndexList = vals.Select((value, index) => new { value, index })
                        .Where(x => x.value)
                        .Select(x => x.index)
                        .ToList();
                    result.Data = trueIndexList;
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 设置找板边完成
        /// </summary>
        /// <returns></returns>
        public DataResult SetFindEdgeFinish()
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD100";
            int writeVal = 2;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }


        // 获取设备的模式,0是识别模式,1是直通模式
        public DataResult<int> GetDeviceMode()
        {
            DataResult<int> result = new DataResult<int>();
            string readPos = "DB100.DBD8";
            try
            {
                OperateResult<int> readVal = NetClient.ReadInt32(readPos);
                if (readVal.IsSuccess)
                {
                    result.Data = readVal.Content;
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 设置设备状态, 识别模式和直通模式 0是识别, 1 是直通.
        /// </summary>
        /// <returns></returns>
        public DataResult SetDeviceMode(int writeVal)
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD8";
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 第一次找靶标拍照信号
        /// </summary>
        /// <returns></returns>
        public DataResult<int> GetAllowFindTargetFirst()
        {
            DataResult<int> result = new DataResult<int>();
            string readPos = "DB100.DBD108";
            try
            {
                OperateResult<int> readVal = NetClient.ReadInt32(readPos);
                if (readVal.IsSuccess)
                {
                    result.Data = readVal.Content;
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 第一次找靶标结束
        /// </summary>
        /// <returns></returns>
        public DataResult SetFindTargetFirstFinish()
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD108";
            int writeVal = 2;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 第二次找靶标拍照信号
        /// </summary>
        /// <returns></returns>
        public DataResult<int> GetAllowFindTargetSecond()
        {
            DataResult<int> result = new DataResult<int>();
            string readPos = "DB100.DBD116";
            try
            {
                OperateResult<int> readVal = NetClient.ReadInt32(readPos);
                if (readVal.IsSuccess)
                {
                    result.Data = readVal.Content;
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 第二次找靶标结束
        /// </summary>
        /// <returns></returns>
        public DataResult SetFindTargetSecondFinish()
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD116";
            int writeVal = 2;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 设置第一次找靶标移动距离,单位就是mm,直接转换为整数,不需要精度那么高
        /// </summary>
        /// <returns></returns>
        public DataResult SetFirstMove(int dismm)
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD104";
            int writeVal = dismm;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }


        /// <summary>
        /// 设置第二次找靶标移动距离,单位就是mm,直接转换为整数,精度不需要那么高
        /// </summary>
        /// <returns></returns>
        public DataResult SetSecondMove(int dismm)
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD112";
            int writeVal = dismm;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 设置靶距Y
        /// </summary>
        /// <returns></returns>
        public DataResult SetTargetDisY(int dismm)
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD216";
            int writeVal = dismm;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        // 设置识别结果
        // 1. 直流(Direct)  2. 旋转(Rotate)
        // 3. 翻转(Flip)   4. (旋转加翻转)RotateAndFlip
        public DataResult SetCalcResult(CalcResType resType)
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD120";
            int writeVal = (int)resType;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        /// <summary>
        /// 读取Xray电流电压
        /// </summary>
        /// <returns></returns>
        public DataResult<float[]> GetXrayParams()
        {
            DataResult<float[]> result = new DataResult<float[]>();
            float[] data = new float[4];
            string readPos = "DB100.DBD200";
            try
            {
                OperateResult<float[]> readVal = NetClient.ReadFloat(readPos, 4);
                if (readVal.IsSuccess)
                {
                    data[0] = readVal.Content[0];
                    GlobalValues.dyxray01 = data[0];
                    data[1] = readVal.Content[1];
                    GlobalValues.dlxray01 = data[1];
                    data[2] = readVal.Content[2];
                    GlobalValues.dyxray02 = data[2];
                    data[3] = readVal.Content[3];
                    GlobalValues.dlxray02 = data[3];
                    result.Data = data;
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        // 1, 2, 3 启动停止复位
        public DataResult StartPlc()
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD32";
            int writeVal = 1;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        // 停止,赋值为2
        public DataResult StopPlc()
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD32";
            int writeVal = 2;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        // 复位,赋值为3
        public DataResult ResetPlc()
        {
            DataResult result = new DataResult();
            string writePos = "DB100.DBD32";
            int writeVal = 3;
            try
            {
                OperateResult writeRes = NetClient.Write(writePos, writeVal);
                if (writeRes.IsSuccess)
                {
                    result.State = true;
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }

        // 获取PLC的运行状态, DB100.DBD4
        // 0 无, 1手动中,停止中 2 自动中运行中 3复位中 4故障中
        public DataResult<int> GetPlcRunningState()
        {
            DataResult<int> result = new DataResult<int>();
            string readPos = "DB100.DBD4";
            try
            {
                OperateResult<int> readVal = NetClient.ReadInt32(readPos);
                if (readVal.IsSuccess)
                {
                    result.Data = readVal.Content;
                    result.State = true;
                }
                else
                {
                    // PLC通信异常,再连接并且读取一次,如果还是失败,就报错
                    DataResult connResult = ConnectPlc();
                    if (connResult.State)
                    {
                        readVal = NetClient.ReadInt32(readPos);
                        if (readVal.IsSuccess)
                        {
                            result.Data = readVal.Content;
                            result.State = true;
                        }
                    }
                    else
                    {
                        result.Message = connResult.Message;
                    }
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            return result;
        }


    }
}
